---
title: Theming
description: Best practices for theming in Unistyles
---

import { Card, Aside } from '@astrojs/starlight/components'
import Seo from '../../../../components/Seo.astro'

<Seo
    seo={{
        title: 'Theming guide',
        description: 'Best practices for theming in Unistyles'
    }}
>

Theming in `Unistyles` differs from other libraries as it doesn't impose any specific syntax.

**Any JavaScript object can be a Unistyles theme**.

There is also no limit to the number of themes. You can even register dozens of them eg. when you needs to support some premium ones.

Theming is optional. If you don't register themes with [StyleSheet.configure](/v3/start/configuration#themes-optional)
the library will use an empty object by default.

### Create a theme

You can organize your themes however you want:

```tsx
const myTheme = {
    // any keys
    colors: {
        // your colors
    },
    components: {
        // any number of nesting
        button: {
            deepKey: {}
        }
    },
    utils: {
        // you can even use functions here
        hexToRGBA: () => {}
    },
    // or compute your themes with functions and spread operators
    ...premiumFeatures,
    ...getMyColors()
}
```

<Aside>
    It's also possible to update the theme during runtime. Please check `updateTheme` method in the [UnistylesRuntime](/v3/references/unistyles-runtime) guide.
</Aside>

If you use TypeScript you need to override the library's type:

```tsx /name/
type AppThemes = {
  name: typeof myTheme
}

declare module 'react-native-unistyles' {
  export interface UnistylesThemes extends AppThemes {}
}
```

Finally, to register the theme, you need to call `StyleSheet.configure`:

```tsx /name/
import { StyleSheet } from 'react-native-unistyles'
import { myTheme } from './themes'

StyleSheet.configure({
    themes: {
        name: myTheme,
        // you can add more themes here
    }
})
```

Where `name` is the unique name of your theme.

<Aside>
It's not recommended to use themes with different shapes.
Unistyles allows that, but it might cause some TypeScript errors.
</Aside>

### Select theme

If you've registered more than one theme, Unistyles won't know which one is the initial one.
At this point, you have 3 options:

- If you know the initial theme upfront, select it with `settings` from [StyleSheet.configure](/v3/start/configuration#settings-optional)

```tsx /initialTheme/
StyleSheet.configure({
    settings: {
        initialTheme: 'premium'
    }
})
```

- If you need to resolve the user-selected theme during runtime, use a synchronous function:

```tsx /initialTheme/
StyleSheet.configure({
    settings: {
        initialTheme: () =>  {
            // get preferred theme from user's preferences/MMKV/SQL/StanJS etc.
            return storage.getString('preferredTheme') ?? 'light'
        }
    }
})
```

<Aside>
It's not possible to use `async` functions with `initialTheme` option.
</Aside>

- Use adaptive themes, which are described below

### Get the current theme

To get the current theme you can access it in the `StyleSheet.create` function:

```tsx /theme/
const styles = StyleSheet.create(theme => ({
    ...
}))
```

Other, discouraged way is to access it in the hook `useUnistyles`:

```tsx /useUnistyles/
import { useUnistyles } from 'react-native-unistyles'

const MyComponent = () => {
    const { theme } = useUnistyles()

    return (
        <Text>
            My theme is {theme.colors.primary}
        </Text>
    )
}
```

:::caution
`useUnistyles` is not recommended as it will re-render your component on every change of the theme. Learn more about [useUnistyles](/v3/references/use-unistyles)
:::

### Get the current theme name

To get the current theme name, import `UnistylesRuntime`:

```tsx /UnistylesRuntime.themeName/
import { UnistylesRuntime } from 'react-native-unistyles'

// access the current theme name in your component
export const UserTheme = () => (
    <Text>
        Selected theme is {UnistylesRuntime.themeName}
    </Text>
)
```

### Adaptive themes

Adaptive themes allow Unistyles to automatically manage the selection of your themes based on device color scheme settings.
To enable this, you need to meet two conditions:

- register two themes with reserved names `light` and `dark`:

```tsx /light:/ /dark:/
StyleSheet.configure({
    themes: {
        light: lightTheme,
        dark: darkTheme,
        // you may have more themes
    }
})
```

- Explicitly enable  `adaptiveThemes`:

```tsx /adaptiveThemes/
StyleSheet.configure({
    themes: {
        light: lightTheme,
        dark: darkTheme
    },
    settings: {
        adaptiveThemes: true
    }
})
```

<Aside type="caution">
Setting initial theme and enabling adaptive themes at the same time will throw an error as this options are mutually exclusive.
</Aside>

### Toggle adaptive themes during runtime

To toggle adaptive themes support at any point, use `UnistylesRuntime`:

```tsx /UnistylesRuntime.setAdaptiveThemes.*/
import { UnistylesRuntime } from 'react-native-unistyles'

// toggle support for adaptive themes at any point
export const ToggleAdaptiveThemes = () => (
    <Button
        title="Disable adaptive themes"
        onPress={() => UnistylesRuntime.setAdaptiveThemes(false)}
    />
)
```

With adaptive themes disabled, you can now manually change the theme.

### Check if adaptive themes are enabled

To check if adaptive themes are enabled, use `UnistylesRuntime` again:

```tsx /UnistylesRuntime.hasAdaptiveThemes/
import { UnistylesRuntime } from 'react-native-unistyles'

// check if you've enabled adaptive themes
export const AdaptiveThemes = () => (
    <Text>
        Adaptive themes are {UnistylesRuntime.hasAdaptiveThemes ? 'enabled' : 'disabled'}
    </Text>
)
```

### Get device color scheme

Check your device color preference with `UnistylesRuntime`:

```tsx /colorScheme/
import { UnistylesRuntime } from 'react-native-unistyles'

// check the current device scheme preference
export const UserTheme = () => (
    <Text>
        My device is using the {UnistylesRuntime.colorScheme} scheme.
    </Text>
)
```

Available options are: `dark`, `light` or `unspecified` for devices that don't support color schemes.

:::caution
Unistyles will read your device settings, not user preferences. It's not compatible with the React Native `Appearance` module.
:::

If your app's theme is not changing based on device settings, please refer to the [FAQ](/v3/other/frequently-asked-questions/#adaptive-mode-doesnt-work-for-me)

### Change theme

To change the theme at any time, simply call `setTheme` function:

```tsx /UnistylesRuntime.setTheme.*/
import { UnistylesRuntime } from 'react-native-unistyles'

// change the theme in any component
export const ChangeTheme = () => (
    <Button
        title="Change theme"
        onPress={() => UnistylesRuntime.setTheme('dark')}
    />
)
```
<Aside type="caution">
Calling this function with enabled adaptive themes will throw an error.
</Aside>

### Update theme during runtime

Unistyles allows you to update your theme during runtime. This is useful if you want to show the user interface with default colors and later alter theme based on user preferences.

If you update the currently selected theme, it will be automatically applied, and Unistyles will notify all stylesheets about the change. Otherwise, theme will be updated silently.

To update the theme during runtime, call `updateTheme` function, and return new theme object:

```tsx /UnistylesRuntime.updateTheme/
import { UnistylesRuntime } from 'react-native-unistyles'

// update the theme at any time
export const UpdateTheme = ({ selectedColors }) => (
    <Button
        title="Update theme"
        onPress={() => UnistylesRuntime.updateTheme('dark', currentTheme => ({
            ...currentTheme,
            colors: {
                ...currentTheme.colors,
                ...selectedColors
            }
        }))}
    />
)
```

### Update rootView background color during runtime

You can also change dynamically the root view background color with `UnistylesRuntime`:

```tsx /UnistylesRuntime.setRootViewBackgroundColor/
import { UnistylesRuntime } from 'react-native-unistyles'

// update the theme at any time
export const UpdateTheme = ({ selectedColors }) => (
    <Button
        title="Update theme"
        onPress={() => UnistylesRuntime.setRootViewBackgroundColor(theme.colors.primary)}
    />
)
```

Changing rootView background color is useful when your app supports different orientations and you want to match the background color with your theme while transitioning.

<Aside>
Unistyles supports all colors that React Native supports eg. #FFFFFF, rgba(255, 255, 255, 0.5), red etc.
</Aside>

</Seo>
